
#include <string.h> 

#include "Utility.h"
#include "BSP_WG_In.h"
#include "WG.h"
#include "Bit.h"
#include "Timer.h"
#include "Env.h"

static Timer_T wgTimer;
static volatile uint8_t wgInFlag;
static uint8_t wgInBuf[10];
static uint8_t wgInCount;

static void WG_TimerCallback(void){
	if(7 < wgInCount && wgInCount < 67){
		wgInFlag = 1;
	}
	else{
		wgInCount = 0;
	}
}

static void WG_In_Callback(uint8_t bit){
	if(wgInFlag){
		return;
	}
	Timer_Restart(&wgTimer);
	if(wgInCount < 66){
		BitBuffer_write(wgInBuf, wgInCount, bit);
		wgInCount++;
	}
	else{
		if(wgInCount < 67){
			wgInCount++;
		}
	}
}


void WG_In_Init(void){	
	BSP_WG_In_SetCallback(WG_In_Callback);
	Timer_Setup(&wgTimer, 2, 0, 0, WG_TimerCallback);
	wgInFlag = 0;
}

static int Buffer_SetBitCount(uint8_t buf[], uint8_t off, uint8_t nbit){
	uint8_t count = 0;
	uint8_t i;
	
	for(i = off; i < (nbit + off); ++i){
		uint8_t val = BitBuffer_read(buf, i);
		if(val != 0){
			++count;
		}
	}
	return count;
}

static void WG_SetBit(uint8_t* buf, uint8_t num, uint8_t val){
	unsigned char byteOffset = num >> 3;
	unsigned char bitOffset = num & 0x07;

	if(val){
		buf[byteOffset] |= (uint8_t)0x80 >> bitOffset;
	}
	else{
		buf[byteOffset] &= ~((uint8_t)0x80 >> bitOffset);
	}	
}

static int WG_In_Card(uint8_t wgBits[], uint8_t nBit, uint8_t buf[]){
	uint8_t i;
	uint8_t pos;
	uint8_t half = nBit / 2;
	uint8_t count = Buffer_SetBitCount(wgBits, 0, half);
	uint8_t nbyte = nBit / 8;
	if(count & 0x01){
		return -2;
	}
	count = Buffer_SetBitCount(wgBits, half, half);
	if(!(count & 0x01)){
		return -3;
	}
	for(i = 0, pos = 1; i < nbyte * 8; ++i, ++pos){
		uint8_t val = BitBuffer_read(wgBits, pos);
		WG_SetBit(buf, i, val);
	}
	if(envProp.wgReverse){
		Mem_Reverse(buf, nbyte);
	}
	return nbyte;
}

static int WG_In_Card1(uint8_t wgBits[], uint8_t nBit, uint8_t buf[]){
	uint8_t i;
	uint8_t pos;
	uint8_t half = nBit / 2;
	uint8_t count = Buffer_SetBitCount(wgBits, 0, half);
	uint8_t nbyte = nBit / 8;
	if(count & 0x01){
		return -2;
	}
	count = Buffer_SetBitCount(wgBits, half, half);
	if(!(count & 0x01)){
		return -3;
	}
	for(i = 0, pos = 1; i < nbyte * 8; ++i, ++pos){
		uint8_t val = BitBuffer_read(wgBits, pos);
		WG_SetBit(buf, i, val);
	}
	
	return nbyte;
}



static uint8_t WG_ValToKey(uint8_t val){
	uint8_t key;
	
	switch(val){
	case 0x0A: key = '*'; break;
	case 0x0B: key = '#'; break;
	default: key = val; break;
	}
	return key;
}

static int WG_In_Key(uint8_t wgBits[], uint8_t count, uint8_t buf[]){
	uint8_t wgKey = 0;
	uint8_t val;
	uint8_t inv;
	uint8_t i;
	uint8_t pos;
	
	for(i = 0, pos = 0; i < count; ++i, ++pos){
		uint8_t val = BitBuffer_read(wgBits, pos);
		WG_SetBit(&wgKey, i, val);
	}
	val = wgKey & 0x0F;
	inv = (0xF - wgKey) << 4;
	if((wgKey & 0xF0) == inv){
		buf[0] = WG_ValToKey(val);
		return count / 8;
	}
	return -1;
}

int WG_In_Get(uint8_t buf[]){
	int ret = -1;
	if(wgInFlag == 1){
		wgInFlag = 0;
		if(wgInCount & 0x01){
			ret = -1;
		}
		else
		if(wgInCount > 8){
			ret = WG_In_Card(wgInBuf, wgInCount, buf);
		}
		else
		if(wgInCount == 8){
			ret = WG_In_Key(wgInBuf, wgInCount, buf);
		}
		wgInCount = 0;
	}
	return ret;
}


int WG_In_Get1(uint8_t buf[]){
	int ret = -1;
	if(wgInFlag == 1){
		wgInFlag = 0;
		if(wgInCount & 0x01){
			ret = -1;
		}
		else
		if(wgInCount > 8){
			ret = WG_In_Card1(wgInBuf, wgInCount, buf);
		}
		else
		if(wgInCount == 8){
			ret = WG_In_Key(wgInBuf, wgInCount, buf);
		}
		wgInCount = 0;
	}
	return ret;
}


